home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / hypercar / xcmd / dartxcmd.sit / Dartmouth XCMD's 3.1 / card_2454.txt < prev    next >
Encoding:
Text File  |  1989-06-02  |  19.6 KB  |  580 lines

  1. -- card: 2454 from stack: in.1
  2. -- bmap block id: 0
  3. -- flags: 0000
  4. -- background id: 3241
  5. -- name: DeleteResFork
  6. ----- HyperTalk script -----
  7. on Install
  8.   get ChooseTargetStack()
  9.   InstallResource XCMD,DeleteResFork,it
  10. end Install
  11.  
  12.  
  13. -- part 3 (button)
  14. -- low flags: 00
  15. -- high flags: A003
  16. -- rect: left=64 top=300 right=322 bottom=202
  17. -- title width / last selected line: 0
  18. -- icon id / first selected line: 0 / 0
  19. -- text alignment: 1
  20. -- font id: 0
  21. -- text size: 12
  22. -- style flags: 0
  23. -- line height: 16
  24. -- part name: DeleteResFork
  25. ----- HyperTalk script -----
  26. on mouseUp
  27.   -- This button uses the DeleteResFork XCMD to delete the
  28.   -- resource fork of a stack.
  29.   deleteresfork
  30.   get the result
  31.   if it is not empty then put it
  32. end mouseUp
  33.  
  34.  
  35.  
  36. -- part 4 (field)
  37. -- low flags: 81
  38. -- high flags: 2007
  39. -- rect: left=12 top=26 right=298 bottom=491
  40. -- title width / last selected line: 0
  41. -- icon id / first selected line: 0 / 0
  42. -- text alignment: 0
  43. -- font id: 22
  44. -- text size: 10
  45. -- style flags: 0
  46. -- line height: 13
  47. -- part name: Source
  48.  
  49.  
  50. -- part 6 (button)
  51. -- low flags: 00
  52. -- high flags: A003
  53. -- rect: left=299 top=300 right=322 bottom=438
  54. -- title width / last selected line: 0
  55. -- icon id / first selected line: 0 / 0
  56. -- text alignment: 1
  57. -- font id: 0
  58. -- text size: 12
  59. -- style flags: 0
  60. -- line height: 16
  61. -- part name: Show Pascal Source
  62. ----- HyperTalk script -----
  63. on mouseUp
  64.   set the visible of card field 1 to not the visible of card field 1
  65.   if the visible of card field 1 is true then
  66.     set the name of me to "Hide Pascal Source"
  67.   else set the name of me to "Show Pascal Source"
  68. end mouseUp
  69.  
  70.  
  71.  
  72. -- part contents for background part 16
  73. ----- text -----
  74. DELETERESFORK XCMD version 1.5
  75. Kevin Calhoun
  76.  
  77. DeleteResFork deletes the resource fork of a stack while leaving the data fork intact.
  78.  
  79. Each Macintosh file, including HyperCard stacks, has two forks--a resource fork and a data fork, either of which may be empty.  HyperCard stores all the information about buttons, fields, text, and pictures in the data fork of your stacks.  XCMD's, XFCN's, PICT's, and other resources are stored in the resource fork.
  80.  
  81. DeleteResFork is for that trying moment when you discover that the resource fork of a stack has been ruined.  If this should occur, all of the data HyperCard relies on will still be intact--it's stored in the data fork--but you'll need to jettison your garbled resource fork and then re-install the necessary resources.
  82.  
  83. How can you tell if the resource fork has been ruined?  If ResEdit tells you that there was an error while opening the stack or if a disk utility tells you that the resource fork still takes up disk space even though HyperCard can't find the resources, then you know that your resource fork has been compromised.  (Sometimes HyperCard can't find newly copied resources until you close the stack and then reopen it.  Don't panic until after you've tried this.)
  84.  
  85. DeleteResFork won't let you regain access to a ruined resource fork.  Instead, it just gets rid of it.  It lets you "shake loose" a worthless resource fork that can't be read and start afresh.
  86.  
  87. NOTE:  It's unwise to delete the resource fork of a stack that is already open.  Make a copy of the stack and then work on the copy.
  88.  
  89. INVOKING DELETERESFORK
  90.  
  91. DeleteResFork <"fileName">
  92.  
  93. DeleteResFork takes one optional parameter, the full pathname of the file whose resource fork you want to delete.  If the file name is not supplied, a standard file dialog box appears, from which you can select a stack.
  94.  
  95. If the file name supplied is not the full pathname of an extant stack, or if there is any other error, DeleteResFork will return an error message as the Result.  The first word of this message will be "Error."
  96.  
  97. NOTE FOR ADVANCED PROGRAMMERS:
  98. Because XCMD's have no "owned resources" and because there's no official "XCMD Mover," you can never count on resources such as DITL's or STR#'s being around when you need them.  The PrintField XCMD checks for the presence of the proper resources for its dialog.  If they're there it displays its dialog; otherwise it goes ahead and prints without the dialog.  With DeleteResFork, I took a different approach--it creates a dialog without using a DITL resource for the dialog item list.
  99.  
  100. The functions AddButton, AddUserItem, and AddStatText append a new item to a dialog item list in memory.  The function MakeDITL uses these to build an item list from scratch.
  101. (Roger tells me that Tech Note #95, How To Add Items to the Print Dialogs, includes some code that handles the general case of adding an item to an item list.)
  102.  
  103. The drawback to creating a dialog item list on the fly without resources is that you can't alter the text of the dialog without recompiling the source code.  However, in the case of XCMD's it may be more valuable to be certain that a vital resource isn't missing than it is to enable alteration of titles and text without source code.
  104.  
  105. Perhaps the safest procedure is to include both the resources and the code to create them on the fly.  If the resources are present, go ahead and use them.  If not, create them on the fly.
  106.  
  107. DeleteResFork also contains a filter for ModalDialog that handles the usual keyboard equivalents for Cancel (command-period, command-q, command-Q, escape) and OK (return and enter).
  108.  
  109. -- part contents for card part 4
  110. ----- text -----
  111. UNIT DataSaver;
  112.  
  113. { DeleteResFork XCMD ┬⌐ 1988-1989 by the Trustees of Dartmouth College }
  114. { Written by Kevin Calhoun }
  115.  
  116. { This source compatible with MPW Pascal 3.0 }
  117.  
  118. (*
  119. Pascal DeleteResFork.p
  120. Link -m ENTRYPOINT Γêé
  121.      -o "YourFile" Γêé
  122.      -rt XCMD=1659 Γêé
  123.      -sn Main=DeleteResFork Γêé
  124.      DeleteResFork.p.o Γêé
  125.     "{Libraries}"interface.o Γêé
  126.     "{PLibraries}"Paslib.o Γêé
  127.     "{Libraries}"HyperXLib.o
  128. *)
  129.  
  130. {$R-}
  131.  
  132. INTERFACE
  133.   USES
  134.     Types,
  135.     Memory,
  136.     QuickDraw,
  137.     Fonts,
  138.     Dialogs,
  139.     Files,
  140.     Resources,
  141.     Packages,
  142.     OSEvents,
  143.     ToolUtils,
  144.     HyperXCmd;
  145.  
  146.   PROCEDURE EntryPoint (paramPtr : XCMDPtr);
  147.  
  148. IMPLEMENTATION
  149.  
  150.   TYPE
  151. { for creating dialog items }
  152.     dItemPtr = ^dialogItem;
  153.     dItemHndl = ^dItemPtr;
  154.     dialogItem = RECORD
  155.         placeholder : handle;
  156.         displayRect : Rect;
  157.         typeAndDataLength : INTEGER;
  158.       END;
  159.  
  160.   PROCEDURE SaveTheData (paramPtr : XCMDPtr); FORWARD;
  161.  
  162.   PROCEDURE EntryPoint (paramPtr : XCMDPtr);
  163.   BEGIN
  164.     SaveTheData(paramPtr);
  165.   END;
  166.  
  167.   FUNCTION GetScreenBitsBounds: Rect;
  168.   { get screenbits.bounds from the QuickDraw globals }
  169.   TYPE
  170.     LongwordPtr = ^LONGINT;
  171.     BitMapPtr = ^BitMap;
  172.   CONST
  173.     screenBitsOffset = -122;
  174.     CurrentA5 = $904;
  175.   VAR
  176.     screenBitsPtr : BitMapPtr;
  177.     myLongwordPtr : LongwordPtr;
  178.   BEGIN
  179.     myLongwordPtr := LongwordPtr(CurrentA5);
  180.       { myLongwordPtr now points to the pointer to the first QD global }
  181.     myLongwordPtr := LongwordPtr(myLongwordPtr^);
  182.       { myLongwordPtr now points to the first QD global }
  183.     screenBitsPtr := BitMapPtr(myLongwordPtr^ + screenBitsOffset);
  184.       { screenBitsPtr now points to the screenBits BitMap }
  185.     GetScreenBitsBounds := screenBitsPtr^.bounds;
  186.   END;
  187.  
  188.   PROCEDURE GetEventMask (VAR theMask : INTEGER);
  189. { returns the current event mask in theMask }
  190.     CONST
  191.       SysEvtMask = $144;
  192.     TYPE
  193.       IntegerPtr = ^INTEGER;
  194.     VAR
  195.       myIntPtr : IntegerPtr;
  196.   BEGIN
  197.     myIntPtr := IntegerPtr(SysEvtMask);
  198.     theMask := myIntPtr^;
  199.   END;
  200.  
  201.   PROCEDURE CenterRect(VAR r: Rect; inRect: Rect);
  202.     VAR
  203.       hSize, vSize: INTEGER;
  204.       hCoord, vCoord: INTEGER;
  205.   BEGIN
  206.     WITH r DO
  207.       BEGIN
  208.       hCoord := left;
  209.       vCoord := top;
  210.       hSize := right-left;
  211.       vSize := bottom-top;
  212.       END;
  213.     WITH inRect DO
  214.       BEGIN
  215.       hCoord := (right-left - hSize) DIV 2 + left;
  216.       vCoord := (bottom-top - vSize) DIV 2 + top;
  217.       END;
  218.     SetRect(r, hCoord, vCoord, hCoord+hSize, vCoord+vSize);
  219.   END;
  220.  
  221.   PROCEDURE PassReturnValue (paramPtr : XCMDPtr;
  222.                   theMsg : Str255); { set theResult }
  223.   BEGIN
  224.     paramPtr^.returnValue := PasToZero(paramPtr, theMsg);
  225.   END;
  226.  
  227.   FUNCTION MyFilter (theDialog : DialogPtr;
  228.                   VAR theEvent : EventRecord;
  229.                   VAR itemHit : INTEGER) : BOOLEAN;
  230. { filter function for modal dialog -- handles the usual key equivalents for OK and Cancel }
  231.     VAR
  232.       theChar : char;
  233.       dummy : EventRecord;
  234.  
  235.     PROCEDURE PushButton (itemNo : INTEGER);
  236. { Hilites the button itemNo while a key is pressed. }
  237. { For this to work properly, the event mask must be set to allow }
  238. { keyUp events to be detected -- that's why the call to ModalDialog, }
  239. { below, is bracketed by calls to SetEventMask. }
  240.       VAR
  241.         itemType : INTEGER;
  242.         itemHandle : Handle;
  243.         itemBox : Rect;
  244.     BEGIN
  245.       GetDItem(theDialog, itemNo, itemType, itemHandle, itemBox);
  246.       HiliteControl(ControlHandle(itemHandle), inButton);
  247.       REPEAT
  248.       UNTIL OSEventAvail(keyUpMask, dummy);
  249.       HiliteControl(ControlHandle(itemHandle), 0);
  250.     END;
  251.  
  252.   BEGIN
  253.     MyFilter := FALSE;
  254.     CASE theEvent.what OF
  255.       keyDown, autoKey : 
  256.         BEGIN
  257.           theChar := CHR(BitAnd(theEvent.message, charCodeMask));
  258.           IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN
  259.             BEGIN
  260.               MyFilter := TRUE;
  261.               CASE ORD(theChar) OF
  262.                 46, 81, 113 :
  263. { if user pressed command-period, -q, or -Q, then do Cancel }
  264.                   BEGIN
  265.                     PushButton(Cancel);
  266.                     itemHit := Cancel;
  267.                     MyFilter := TRUE;
  268.                   END;
  269.               END;
  270.             END
  271.           ELSE
  272.             CASE ORD(theChar) OF
  273.               13, 3 :
  274. { if the user pressed return or enter, do OK }
  275.                 BEGIN
  276.                   PushButton(OK);
  277.                   itemHit := OK;
  278.                   MyFilter := TRUE;
  279.                 END;
  280.               27, 96 :
  281. { if user pressed the escape key or the tilde key, do Cancel }
  282.                 BEGIN
  283.                   PushButton(Cancel);
  284.                   itemHit := Cancel;
  285.                   MyFilter := TRUE;
  286.                 END;
  287.             END;
  288.         END;
  289.     END;
  290.   END;
  291.  
  292.   PROCEDURE DrawBoxAroundDefault (theWindow : WindowPtr;
  293.                   itemNo : INTEGER);
  294.     VAR
  295.       itemType : integer;
  296.       itemHdl : Handle;
  297.       itemBox : rect;
  298.   BEGIN
  299.     GetDItem(theWindow, 1, itemType, itemHdl, itemBox);
  300.     PenSize(3, 3);
  301.     InsetRect(itemBox, -4, -4);
  302.     FrameRoundRect(itemBox, 16, 16);
  303.     PenSize(1, 1);
  304.   END;
  305.  
  306.   PROCEDURE DrawVersionInfo (theWindow : WindowPtr;
  307.                   itemNo : INTEGER);
  308.     VAR
  309.       itemType : integer;
  310.       itemHdl : Handle;
  311.       itemBox : rect;
  312.       str : Str255;
  313.   BEGIN
  314.     str := 'DeleteResFork XCMD 1.5   ┬⌐1989 Dartmouth College';
  315.     GetDItem(theWindow, itemNo, itemType, itemHdl, itemBox);
  316.     TextFont(Geneva);
  317.     TextSize(9);
  318.     TextBox(POINTER(ORD(@str) + 1), LENGTH(str), itemBox, teJustLeft);
  319.     TextFont(SystemFont);
  320.     TextSize(12);
  321.   END;
  322.  
  323.   FUNCTION AddButton (boundsRect : rect;
  324.                   title : Str255;
  325.                   VAR theItems : Handle) : OSErr;
  326. { add information for a new button item to the end of the DITL theItems }
  327.     VAR
  328.       newItem : DItemHndl;
  329.       err : OSErr;
  330.   BEGIN
  331.     newItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  332.     err := MemError;
  333.     IF (newItem <> NIL) AND (err = noErr) THEN
  334.       BEGIN
  335.         MoveHHi(Handle(newItem));
  336.         HLock(Handle(newItem));
  337.         WITH newItem^^ DO
  338.           BEGIN
  339.             placeholder := NIL;
  340.             displayRect := boundsRect;  { display rectangle }
  341.             typeAndDataLength := (ctrlItem + btnCtrl) * 256 + LENGTH(title);
  342.                      { high byte contains itemType, low byte contains length of the button title }
  343.           END;
  344.         err := HandAndHand(Handle(newItem), theItems);  { copy this info into item list }
  345.         IF err = noErr THEN
  346.           err := PtrAndHand(POINTER(ORD4(@title) + 1), theItems, LENGTH(title));
  347.                { copy the characters of the title into the item list }
  348.         HUnlock(Handle(newItem));
  349.         DisposHandle(Handle(newItem));
  350.       END;
  351.     AddButton := err;
  352.   END;
  353.  
  354.   FUNCTION AddUserItem (boundsRect : rect;
  355.                   theProc : ProcPtr;
  356.                   VAR theItems : Handle) : OSErr;
  357.     VAR
  358.       theUserItem : DItemHndl;
  359.       err : OSErr;
  360.   BEGIN
  361.     theUserItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  362.     err := MemError;
  363.     IF (theUserItem <> NIL) AND (err = noErr) THEN
  364.       BEGIN
  365.         MoveHHi(Handle(theUserItem));
  366.         HLock(Handle(theUserItem));
  367.         WITH theUserItem^^ DO
  368.           BEGIN
  369.             placeholder := Handle(theProc);
  370.             displayRect := boundsRect;
  371.             typeAndDataLength := userItem * 256 + 0;
  372.           END;
  373.         err := HandAndHand(Handle(theUserItem), theItems);
  374.         HUnlock(Handle(theUserItem));
  375.         DisposHandle(Handle(theUserItem));
  376.       END;
  377.     AddUserItem := err;
  378.   END;
  379.  
  380.   FUNCTION AddStatText (boundsRect : rect;
  381.                   str : Str255;
  382.                   VAR theItems : Handle) : OSErr;
  383.     VAR
  384.       theStatTextItem : DItemHndl;
  385.       err : OSErr;
  386.   BEGIN
  387.     theStatTextItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  388.     err := MemError;
  389.     IF (theStatTextItem <> NIL) AND (err = noErr) THEN
  390.       BEGIN
  391.         MoveHHi(Handle(theStatTextItem));
  392.         HLock(Handle(theStatTextItem));
  393.         WITH theStatTextItem^^ DO
  394.           BEGIN
  395.             placeholder := NIL;
  396.             displayRect := boundsRect;
  397.             typeAndDataLength := (statText + itemDisable) * 256 + LENGTH(str);
  398.           END;
  399.         err := HandAndHand(Handle(theStatTextItem), theItems);
  400.         IF err = noErr THEN
  401.           err := PtrAndHand(POINTER(ORD4(@str) + 1), theItems, LENGTH(str));
  402.         HUnlock(Handle(theStatTextItem));
  403.         DisposHandle(Handle(theStatTextItem));
  404.       END;
  405.     AddStatText := err;
  406.   END;
  407.  
  408.   FUNCTION MakeDITL (VAR theItems : Handle) : OSErr;
  409. { Create our dialog item list on the fly. }
  410. { We rely heavily on the information given in IM-I, p. 427 }
  411.     CONST
  412.       numItems = 6;
  413.     VAR
  414.       myStatTextItem : dItemHndl;
  415.       err : OSErr;
  416.       itemCount : INTEGER;
  417.       str : Str255;
  418.       theRect : Rect;
  419.   BEGIN
  420.     theItems := NewHandle(2);
  421. { we'll build this handle into a full item list by appending info to it }
  422. { for each item we want to add with HandAndHand and PtrAndHand }
  423.     IF theItems <> NIL THEN
  424.       BEGIN
  425.         itemCount := numItems - 1;
  426.         BlockMove(@itemCount, theItems^, 2);
  427. { first two bytes of the DITL = number of items in list minus 1 }
  428.         SetRect(theRect, 230, 100, 300, 120);
  429.         err := AddButton(theRect, 'OK', theItems);
  430.         IF err = noErr THEN
  431.           BEGIN
  432.             SetRect(theRect, 140, 100, 210, 120);
  433.             err := AddButton(theRect, 'Cancel', theItems);
  434.             IF err = noErr THEN
  435.               BEGIN
  436.                 SetRect(theRect, 220, 90, 310, 130);
  437.                 err := AddUserItem(theRect, @DrawBoxAroundDefault, theItems);
  438.                 IF err = noErr THEN
  439.                   BEGIN
  440.                     SetRect(theRect, 10, 97, 130, 125);
  441.                     err := AddUserItem(theRect, @DrawVersionInfo, theItems);
  442.                     IF err = noErr THEN
  443.                       BEGIN
  444.                         SetRect(theRect, 10, 10, 302, 50);
  445.                         str := 'Are you sure you want to delete the resource fork of: ';
  446.                         err := AddStatText(theRect, str, theItems);
  447.                         IF err = noErr THEN
  448.                           BEGIN
  449.                             SetRect(theRect, 10, 52, 302, 92);
  450.                             str := 'ΓÇ£^0ΓÇ¥? ';
  451.                             err := AddStatText(theRect, str, theItems);
  452.                           END;  { if err = noErr when creating the first statText item }
  453.                       END;  { if err = noErr when creating the version info userItem }
  454.                   END;  { if err = noErr when creating the default button userItem }
  455.               END;  { if err = noErr when creating Cancel Button }
  456.           END;  { if err = noErr when creating OK button }
  457.       END; { if theItems <> nil }
  458.     MakeDITL := err;
  459.   END;
  460.  
  461.   PROCEDURE DoSFGet (VAR SFGetReply : SFReply);
  462.     VAR
  463.       where : point;
  464.       typeList : SFTypeList;
  465.       dlgt: DialogTHndl;
  466.       r: rect;
  467.       screen: rect;
  468.       h, v: INTEGER;
  469.   BEGIN  { select text file to read using SFGetFile }
  470.     dlgt := DialogTHndl(GetResource('DLOG',getDlgID));
  471.     if dlgt <> nil then
  472.       begin
  473.       r := dlgt^^.boundsRect;
  474.       screen := GetScreenBitsBounds;
  475.       h := ((screen.right - screen.left) - (r.right - r.left)) div 2;
  476.       v := ((screen.bottom - screen.top) - (r.bottom - r.top)) div 2;
  477.       SetPt(where, h, v);
  478.       end
  479.     else SetPt(where, 82, 75);
  480.     typeList[0] := 'STAK';                { tell SFGetFile to display only text files }
  481.     SFGetFile(where, '', NIL, 1, typeList, NIL, SFGetReply);          { call SFGetFile }
  482.   END;
  483.  
  484.   FUNCTION DeleteResourceFork (fName : Str255;
  485.                   vRefNum : INTEGER) : OSErr;
  486. { delete the resource fork of a file }
  487.     VAR
  488.       theRefNum : INTEGER;
  489.       closeErr, err : OSErr;
  490.   BEGIN
  491.     err := OpenRF(fName, vRefNum, theRefNum);  { open the file }
  492.  
  493.     IF err = noErr THEN              { continue only if file could be opened }
  494.       BEGIN
  495.         err := SetEOF(theRefNum, 0);  { set the length of the resource fork to 0 }
  496.         closeErr := FSClose(theRefNum);  { close the file }
  497.       END;
  498.     DeleteResourceFork := err;
  499.   END; { procedure DeleteResourceFork }
  500.  
  501.   PROCEDURE SaveTheData (paramPtr : XCMDPtr);
  502.     VAR
  503.       err : OSErr;
  504.       SFGetReply : SFReply;
  505.       gotAFile : BOOLEAN;
  506.       theFileName : Str255;
  507.       theVRefNum : INTEGER;
  508.       fndrInfo : FInfo;
  509.       myItems : Handle;
  510.       bounds : rect;
  511.       myDialog : DialogPtr;
  512.       theMask : INTEGER;
  513.       itemHit : INTEGER;
  514.       numStr : Str255;
  515.  
  516.   BEGIN { procedure SaveTheData }
  517.     gotAFile := FALSE;
  518.     IF paramPtr^.paramCount < 1 THEN
  519. { user did not specify a file -- put up standard file dialog box }
  520.       BEGIN
  521.         DoSFGet(SFGetReply);
  522.         SendCardMessage(paramPtr, 'go to this card');
  523.         IF SFGetReply.good THEN
  524.           BEGIN         { continue only if user actually selected a file }
  525.             WITH SFGetReply DO
  526.               BEGIN
  527.                 theFileName := fName;
  528.                 theVRefNum := vRefNum;
  529.               END;  { with SFGetReply }
  530.             gotAFile := TRUE;
  531.           END;
  532.       END
  533.     ELSE
  534. { user specified a file -- check to see if it's really a stack }
  535.       BEGIN
  536.         ZeroToPas(paramPtr, paramPtr^.params[1]^, theFileName);
  537.         err := GetFInfo(theFileName, 0, fndrInfo);
  538.         IF (err = noErr) AND (fndrInfo.fdType = 'STAK') THEN
  539.           BEGIN
  540.             gotAFile := TRUE;
  541.             theVRefNum := 0;
  542.           END
  543.         ELSE IF err <> noErr THEN
  544.           BEGIN
  545.           NumToStr(paramPtr, err, numStr);
  546.           PassReturnValue(paramPtr, CONCAT('Error ', numStr));
  547.           END
  548.         ELSE
  549.           PassReturnValue(paramPtr, 'Error -- that file is not a stack');
  550.       END;
  551.     IF gotAFile THEN
  552.       BEGIN
  553. { create our dialog item list on the fly and put up our dialog }
  554.         err := MakeDITL(myItems);
  555.         IF err = noErr THEN
  556.           BEGIN
  557.             SetRect(bounds, 100, 80, 412, 210);
  558.             CenterRect(bounds, GetScreenBitsBounds);
  559.             ParamText(theFileName, '', '', '');
  560.             myDialog := NewDialog(NIL, bounds, '', TRUE, dBoxProc, POINTER(-1), FALSE, 0, myItems);
  561.             GetEventMask(theMask);
  562.             SetEventMask(everyEvent);
  563.             REPEAT
  564.               ModalDialog(@MyFilter, itemHit);
  565.             UNTIL (itemHit = OK) OR (itemHit = Cancel);
  566.             SetEventMask(theMask);
  567.             DisposDialog(myDialog);
  568.             DisposHandle(myItems);
  569.             IF itemHit = OK THEN
  570.               err := DeleteResourceFork(theFileName, theVRefNum);
  571.           END;
  572.         IF err <> noErr THEN
  573.           BEGIN
  574.           NumToStr(paramPtr, err, numStr);
  575.           PassReturnValue(paramPtr, CONCAT('Error ', numStr));
  576.           END;
  577.       END; { if gotAFile }
  578.   END;
  579.  
  580. END.